package com.googlecode.spreadit.matching;

import com.googlecode.spreadit.bean.Message;
import com.googlecode.spreadit.util.StringUtil;

/**
 * This class models an (unary) {@link Comparison Comparison operation} against
 * a given {@link MessageField field} of a {@link Message}.
 * 
 * This class implements a fluent API (see e.g. <a
 * href="http://en.wikipedia.org/wiki/Fluent_interface#Java"
 * >http://en.wikipedia.org/wiki/Fluent_interface#Java</a>) in conjunction with
 * other classes in this package (i.e., {@link MessageField},
 * {@link MatchExpression}).
 * 
 * @author Markus L. Dechert (markus.dechert@googlemail.com)
 */
public class MatchField extends MatchExpression {

	private static final long serialVersionUID = 2588697698694838843L;

	private MessageField field;

	private String compareString;

	private Comparison operation;

	/**
	 * The fields must be initialized, use
	 * {@link #MatchField(MessageField, String, Relation)}.
	 */
	private MatchField() {
	}

	public MatchField(MessageField field, String compareString,
			Comparison operation) {
		this();
		this.field = field;
		this.compareString = compareString;
		this.operation = operation;
	}

	@Override
	public boolean matches(Message m) {
		String fc = extractFieldContent(m);
		switch (operation) {
		case EQUALS:
			return (fc != null) && fc.equals(compareString);
		case CONTAINS:
			return (fc != null) && fc.contains(compareString);
		case NOT_EQUALS:
			return !((fc != null) && fc.equals(compareString));
		case NOT_CONTAINS:
			return !((fc != null) && fc.contains(compareString));
		default:
			throw new RuntimeException(getClass().getSimpleName()
					+ ": not implemented!");
		}
	}

	protected String extractFieldContent(Message m) {
		switch (field) {
		case SUBJECT:
			return m.getSubject();
		case BODY:
			return m.getBody();
		case INCOMING_CHANNEL:
			return m.getIncomingChannel().toString();
		case SENDER:
			return m.getSender();
		case RECIPIENT:
			return m.getRecipient();
		default:
			throw new RuntimeException(getClass().getSimpleName()
					+ ": not implemented!");
		}

	}

	public MessageField getField() {
		return field;
	}

	public void setField(MessageField field) {
		this.field = field;
	}

	public String getCompareString() {
		return compareString;
	}

	public void setCompareString(String compareString) {
		this.compareString = compareString;
	}

	public Comparison getOperation() {
		return operation;
	}

	public void setOperation(Comparison operation) {
		this.operation = operation;
	}

	@Override
	public String toString() {
		return StringUtil.toCamelCase(field.toString()) + " " + operation
				+ " '" + compareString + "'";
	}

	//
	// Fluent API for the matching
	//
	public MatchTwo and(MatchExpression expr) {
		return new MatchTwo(expr, this, Relation.AND);
	}

	public MatchTwo or(MatchExpression expr) {
		return new MatchTwo(expr, this, Relation.OR);
	}

	public MatchTwo xor(MatchExpression expr) {
		return new MatchTwo(expr, this, Relation.EITHER_OR);
	}
}
